package com.kexio.dynamic.datasource.service;

import org.springframework.stereotype.Component;

/**
 * 租户数据源路由器
 * 
 * 根据当前用户的租户信息自动路由到对应的数据源
 * 
 * @author Kexio
 * @since 1.0.0
 */
@Component
public class TenantDataSourceRouter {

    private static final String MASTER_DS = "master";
    private static final String TENANT_DS_PREFIX = "tenant_";

    /**
     * 确定当前应该使用的数据源
     * 
     * @return 数据源名称
     */
    public String determineCurrentDataSource() {
        try {
            // 从用户上下文获取租户ID
            Long tenantId = getCurrentTenantId();
            
            if (tenantId != null && tenantId > 0) {
                return TENANT_DS_PREFIX + tenantId;
            }
            
            // 如果没有租户信息，使用主库
            return MASTER_DS;
        } catch (Exception e) {
            // 异常情况下使用主库
            return MASTER_DS;
        }
    }

    /**
     * 根据租户ID确定数据源
     * 
     * @param tenantId 租户ID
     * @return 数据源名称
     */
    public String determineDataSourceByTenant(Long tenantId) {
        if (tenantId != null && tenantId > 0) {
            return TENANT_DS_PREFIX + tenantId;
        }
        return MASTER_DS;
    }

    /**
     * 根据用户ID确定数据源
     * 
     * @param userId 用户ID
     * @return 数据源名称
     */
    public String determineDataSourceByUser(Long userId) {
        if (userId == null) {
            return MASTER_DS;
        }
        
        try {
            // 根据用户ID查找租户ID
            Long tenantId = getTenantIdByUserId(userId);
            return determineDataSourceByTenant(tenantId);
        } catch (Exception e) {
            return MASTER_DS;
        }
    }

    /**
     * 检查数据源是否为租户数据源
     * 
     * @param dataSourceName 数据源名称
     * @return 是否为租户数据源
     */
    public boolean isTenantDataSource(String dataSourceName) {
        return dataSourceName != null && dataSourceName.startsWith(TENANT_DS_PREFIX);
    }

    /**
     * 从数据源名称中提取租户ID
     * 
     * @param dataSourceName 数据源名称
     * @return 租户ID
     */
    public Long extractTenantId(String dataSourceName) {
        if (!isTenantDataSource(dataSourceName)) {
            return null;
        }
        
        try {
            String tenantIdStr = dataSourceName.substring(TENANT_DS_PREFIX.length());
            return Long.parseLong(tenantIdStr);
        } catch (NumberFormatException e) {
            return null;
        }
    }

    /**
     * 根据租户类型选择数据源策略
     * 
     * @param tenantType 租户类型
     * @return 数据源策略
     */
    public DataSourceStrategy determineStrategy(String tenantType) {
        if (tenantType == null) {
            return DataSourceStrategy.SHARED;
        }
        
        switch (tenantType.toLowerCase()) {
            case "enterprise":
            case "premium":
                return DataSourceStrategy.DEDICATED;
            case "standard":
                return DataSourceStrategy.SHARED_SCHEMA;
            default:
                return DataSourceStrategy.SHARED;
        }
    }

    /**
     * 获取租户分片数据源
     * 对于大型租户，可能需要分片到多个数据源
     * 
     * @param tenantId 租户ID
     * @param shardKey 分片键
     * @return 分片数据源名称
     */
    public String getShardedDataSource(Long tenantId, String shardKey) {
        if (tenantId == null) {
            return MASTER_DS;
        }
        
        // 简单的分片算法（可根据实际需求调整）
        int shardIndex = Math.abs(shardKey.hashCode()) % getShardCount(tenantId);
        return TENANT_DS_PREFIX + tenantId + "_shard_" + shardIndex;
    }

    /**
     * 验证数据源访问权限
     * 
     * @param dataSourceName 数据源名称
     * @param userId         用户ID
     * @return 是否有访问权限
     */
    public boolean hasAccess(String dataSourceName, Long userId) {
        if (userId == null) {
            return false;
        }
        
        // 主库访问权限检查
        if (MASTER_DS.equals(dataSourceName)) {
            return hasAdminAccess(userId);
        }
        
        // 租户库访问权限检查
        if (isTenantDataSource(dataSourceName)) {
            Long tenantId = extractTenantId(dataSourceName);
            return tenantId != null && belongsToTenant(userId, tenantId);
        }
        
        return false;
    }

    /**
     * 获取当前租户ID
     * 从用户上下文或安全上下文中获取
     * 
     * @return 租户ID
     */
    private Long getCurrentTenantId() {
        // 从UserInfoUtils中获取租户ID
        try {
            return com.kexio.core.security.util.UserInfoUtils.getCurrentTenantId();
        } catch (Exception e) {
            // 在没有用户上下文的情况下（如系统初始化），返回null
            return null;
        }
    }

    /**
     * 根据用户ID获取租户ID
     * 
     * @param userId 用户ID
     * @return 租户ID
     */
    private Long getTenantIdByUserId(Long userId) {
        // TODO: 实现用户-租户关系查询
        // 这里需要查询数据库或缓存
        return null;
    }

    /**
     * 获取租户的分片数量
     * 
     * @param tenantId 租户ID
     * @return 分片数量
     */
    private int getShardCount(Long tenantId) {
        // TODO: 根据租户规模确定分片数量
        // 可以从配置或数据库中获取
        return 1; // 默认不分片
    }

    /**
     * 检查用户是否有管理员权限
     * 
     * @param userId 用户ID
     * @return 是否有管理员权限
     */
    private boolean hasAdminAccess(Long userId) {
        // TODO: 实现管理员权限检查
        return false;
    }

    /**
     * 检查用户是否属于指定租户
     * 
     * @param userId   用户ID
     * @param tenantId 租户ID
     * @return 是否属于该租户
     */
    private boolean belongsToTenant(Long userId, Long tenantId) {
        // TODO: 实现用户-租户关系检查
        return false;
    }

    /**
     * 数据源策略枚举
     */
    public enum DataSourceStrategy {
        /**
         * 共享数据源（所有租户共用）
         */
        SHARED,
        
        /**
         * 共享数据源但不同Schema
         */
        SHARED_SCHEMA,
        
        /**
         * 独立数据源
         */
        DEDICATED,
        
        /**
         * 分片数据源
         */
        SHARDED
    }
}
